﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// 
    /// </summary>
    public class LensDistorsion : BaseImageFilter
    {
        protected double m_main = 0;
        protected double m_edge = 0;
        protected double m_rescale = 0;
        protected double m_brighten = 0;
        protected double m_centre_x = 0;
        protected double m_centre_y = 0;

        /// <summary>
        /// Initializes a new instance of the <see cref="LensDistorsion"/> class.
        /// </summary>
        public LensDistorsion()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LensDistorsion"/> class.
        /// </summary>
        /// <param name="_lensDistorsion">The _lens distorsion.</param>
        internal LensDistorsion(LensDistorsion _lensDistorsion)
        {
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap m_orgImage = (UnsafeBitmap)_bitmap.Clone();
            UnsafeBitmap m_dstImage = (UnsafeBitmap)_bitmap;
            int Width = m_orgImage.Width;
            int Height = m_orgImage.Height;
            int bytesDepth = _bitmap.BytesPerPixelCount;


            // initialize coefficients

            double normallise_radius_sq = 4.0 / (Width * Width + Height * Height);
            double center_x = Width * (100.0 + m_centre_x) / 200.0;
            double center_y = Height * (100.0 + m_centre_y) / 200.0;
            double mult_sq = m_main / 200.0;
            double mult_qd = m_edge / 200.0;
            double rescale = Math.Pow(2.0, -m_rescale / 100.0);
            double brighten = -m_brighten / 10.0;

            /*
             * start at image (i, j), increment by (step, step)
             * output goes to dst, which is w x h x d in size
             * NB: d <= image.bpp
             */

            // We are working on the full image.
            int dstWidth = Width;
            int dstHeight = Height;
            //char dst = (char)data;
            int step = 1, progress;

            int iLimit, jLimit;
            double srcX, srcY, mag;

            iLimit = dstWidth * step;
            jLimit = dstHeight * step;

            //for (int dstJ = 0; dstJ < jLimit; dstJ += step)
            //{
            //    for (int dstI = dstI < iLimit; dstI += step)
            //    {
            // Get source Coordinates.
            double radius_sq;
            double off_x;
            double off_y;
            double radius_mult;

            //        off_x = dstI - center_x;
            //        off_y = dstJ - center_y;
            //        radius_sq = (off_x * off_x) + (off_y * off_y);

            //        radius_sq *= normallise_radius_sq;

            //        radius_mult = radius_sq * mult_sq + radius_sq * radius_sq * mult_qd;
            //        mag = radius_mult;
            //        radius_mult = rescale * (1.0 + radius_mult);

            //        srcX = center_x + radius_mult * off_x;
            //        srcY = center_y + radius_mult * off_y;

            //        brighten = 1.0 + mag * brighten;
            //        pa.pixelAccessGetCubic(srcX, srcY, brighten, dst);
            //        dst += bytesDepth;
            //    }
            //}
            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new LensDistorsion(this);
        }

//        public void Test()
//        {
//            int i;

//            int xInt, yInt;
//            double dx, dy;
//            guchar* corner;

//            xInt = Math.Floor(srcX);
//            dx = srcX - xInt;
//            yInt = Math.Floor(srcY);
//            dy = srcY - yInt;

//#if GATHERING_STATS
//          ++pa->pixelsFound;
//#endif

//            /* we need 4x4 pixels, xInt-1 to xInt+2 horz, yInt-1 to yInt+2 vert */
//            /* they're probably in the last place we looked... */
//            if ((xInt >= pa->tileMinX[0]) && (xInt < pa->tileMaxX[0]) &&
//                (yInt >= pa->tileMinY[0]) && (yInt < pa->tileMaxY[0]))
//            {
//#if GATHERING_STATS
//            ++pa->pixelsFoundInBuffer[0];
//#endif
//                corner = pixelAccessAddress(pa, xInt - 1, yInt - 1);
//                cubicInterpolate(corner, pa->depth * pa->width, pa->depth, dst, dstDepth, dx, dy, brighten);
//                return;
//            }
//        }
    }
}
